<template>
  <div class="article-hall">
    <!-- 顶部导航栏 -->
    <header class="hall-header">
      <div class="header-content">
        <h1 class="hall-title">创作者文章大厅</h1>
        <div class="header-actions">
          <button class="publish-btn" @click="handlePublish">
            <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
              <path d="M12 5v14M5 12h14" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
            </svg>
            发布文章
          </button>
        </div>
      </div>
    </header>

    <!-- 筛选栏 -->
    <div class="filter-bar">
      <div class="filter-content">
        <div class="filter-tabs">
          <button
            v-for="tab in tabs"
            :key="tab.key"
            :class="['tab-btn', { active: activeTab === tab.key }]"
            @click="activeTab = tab.key"
          >
            {{ tab.label }}
          </button>
        </div>
        <div class="filter-tags">
          <button
            v-for="tag in popularTags"
            :key="tag"
            :class="['tag-btn', { active: selectedTag === tag }]"
            @click="selectedTag = selectedTag === tag ? '' : tag"
          >
            {{ tag }}
          </button>
          <div v-if="popularTags.length === 0" style="color: #999; font-size: 12px;">
            暂无类型标签（正在加载...）
          </div>
        </div>
      </div>
    </div>

    <!-- 搜索栏 -->
    <div class="search-bar">
      <div class="search-content">
        <div class="search-input-wrapper">
          <svg class="search-icon" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
            <circle cx="11" cy="11" r="8" stroke="currentColor" stroke-width="2"/>
            <path d="m21 21-4.35-4.35" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
          </svg>
          <input
            v-model="searchKeyword"
            type="text"
            placeholder="搜索文章、作者、标签..."
            class="search-input"
            @input="handleSearch"
          />
        </div>
      </div>
    </div>

    <!-- 文章列表 -->
    <main class="article-list-container">
      <div class="article-list-content">
        <div v-if="loading" class="loading-state">
          <div class="spinner"></div>
          <p>加载中...</p>
        </div>
        <div v-else-if="filteredArticles.length === 0" class="empty-state">
          <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
            <path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z" stroke="currentColor" stroke-width="2"/>
            <circle cx="12" cy="10" r="3" stroke="currentColor" stroke-width="2"/>
          </svg>
          <p>暂无文章</p>
        </div>
        <div v-else class="article-grid">
          <ArticleCard
            v-for="article in filteredArticles"
            :key="article.id"
            :article="article"
            @click="handleArticleClick"
          />
        </div>
        <div ref="infiniteScrollTrigger" class="scroll-trigger"></div>
        <div v-if="!hasMore && filteredArticles.length > 0" class="end-state">
          <p>没有更多文章了</p>
        </div>
      </div>
    </main>
  </div>
</template>

<script setup>
import { ref, computed, onMounted, onBeforeUnmount, watch, nextTick } from 'vue'
import { useRouter } from 'vue-router'
import ArticleCard from '@/components/article/ArticleCard.vue'
import { articleApi, typeApi } from '@/utils/api'

const router = useRouter()

// 响应式数据
const loading = ref(false)
const activeTab = ref('hot')
const selectedTag = ref('')
const searchKeyword = ref('')
const articles = ref([])
const popularTags = ref([]) // 文章类型列表，从后端获取
const hasMore = ref(true)
const infiniteScrollTrigger = ref(null)
const pageSize = 12
const viewedArticleIds = ref([])
let intersectionObserver = null

const tabs = [
  { key: 'hot', label: '热门文章' },
  { key: 'latest', label: '最新文章' },
  { key: 'featured', label: '精选文章' }
]

// 将后端数据转换为前端需要的格式
function transformEssayToArticle(essay) {
  // 处理图片：实际数据中images是数组格式
  let imageUrls = []
  if (essay.images) {
    if (Array.isArray(essay.images)) {
      // 如果已经是数组，直接使用
      imageUrls = essay.images.filter(img => img)
    } else if (typeof essay.images === 'string') {
      // 如果是字符串，用逗号分割（兼容处理）
      imageUrls = essay.images.split(',').map(img => img.trim()).filter(img => img)
    }
  }
  const cover = imageUrls.length > 0 ? imageUrls[0] : null

  // 从内容中提取摘要（前150个字符）
  const excerpt = essay.content
    ? (essay.content.length > 150 ? essay.content.substring(0, 150) + '...' : essay.content)
    : ''

  // 处理用户信息：实际数据中用户信息在user对象中
  const user = essay.user || {}
  const authorName = user.userName || '匿名用户'
  const authorAvatar = user.avatar || null

  // 处理标签：实际数据中标签在types数组中
  const tags = Array.isArray(essay.types) ? essay.types : []

  // 处理点赞数：实际数据中有likeCount字段
  const likeCount = essay.likeCount || 0

  return {
    id: essay.eid || essay.eId, // 注意：实际数据中是eid（小写）
    title: essay.title || '',
    excerpt: excerpt,
    cover: cover,
    authorName: authorName,
    authorAvatar: authorAvatar,
    tags: tags, // 使用实际的types数组
    likeCount: likeCount, // 使用实际的likeCount
    commentCount: 0, // 后端可能没有提供，暂时设为0
    publishTime: essay.createTime || '',
    // 保留原始数据以便后续使用
    rawData: essay
  }
}

// 加载文章列表
async function setupIntersectionObserver() {
  await nextTick()
  if (intersectionObserver) {
    intersectionObserver.disconnect()
    intersectionObserver = null
  }
  if (!infiniteScrollTrigger.value) {
    return
  }
  intersectionObserver = new IntersectionObserver(
    entries => {
      const [entry] = entries
      if (entry && entry.isIntersecting) {
        void loadArticles()
      }
    },
    {
      root: null,
      rootMargin: '0px 0px 200px 0px',
      threshold: 0
    }
  )
  intersectionObserver.observe(infiniteScrollTrigger.value)
}

async function loadArticles() {
  if (loading.value || !hasMore.value) {
    return
  }
  try {
    loading.value = true

    // 根据activeTab确定type参数
    // 默认不传type参数
    let type = undefined

    // 调用API
    const response = await articleApi.listEssay(
      viewedArticleIds.value || [],
      pageSize,
      type,
      searchKeyword.value || undefined
    )

    // 处理响应数据
    // 实际响应格式：{ code: 200, data: Array, message: null }
    let essayList = []
    if (response && typeof response === 'object') {
      // ResultVO格式 { code, message, data }
      if (response.data && Array.isArray(response.data)) {
        essayList = response.data
      } else if (Array.isArray(response)) {
        // 如果response本身就是数组（兼容处理）
        essayList = response
      }
    } else if (Array.isArray(response)) {
      // 直接是数组
      essayList = response
    }

    // 转换为前端格式
    const transformedArticles = essayList.map(transformEssayToArticle)
    const existingViewedSet = new Set((viewedArticleIds.value || []).map(id => String(id)))
    const uniqueNewArticles = transformedArticles.filter(article => {
      const articleId = String(article.id)
      if (!articleId) return false
      if (existingViewedSet.has(articleId)) {
        return false
      }
      existingViewedSet.add(articleId)
      return true
    })

    if (uniqueNewArticles.length > 0) {
      const currentArticles = articles.value || []
      articles.value = [...currentArticles, ...uniqueNewArticles]
      viewedArticleIds.value = Array.from(existingViewedSet)
    }

    if (uniqueNewArticles.length < pageSize) {
      hasMore.value = false
    }
  } catch (error) {
    // 可以在此处添加错误提示
    void error
  } finally {
    loading.value = false
  }
}

// 过滤后的文章
const filteredArticles = computed(() => {
  let result = [...articles.value]

  // 按标签筛选（如果后端提供了标签数据）
  if (selectedTag.value) {
    result = result.filter(article =>
      article.tags && article.tags.includes(selectedTag.value)
    )
  }

  // 搜索关键词（前端二次筛选，后端已经做了主要筛选）
  if (searchKeyword.value) {
    const keyword = searchKeyword.value.toLowerCase()
    result = result.filter(article =>
      article.title.toLowerCase().includes(keyword) ||
      article.excerpt.toLowerCase().includes(keyword) ||
      article.authorName.toLowerCase().includes(keyword) ||
      (article.tags && article.tags.some(tag => tag.toLowerCase().includes(keyword)))
    )
  }

  // 排序
  if (activeTab.value === 'latest') {
    result.sort((a, b) => new Date(b.publishTime).getTime() - new Date(a.publishTime).getTime())
  } else if (activeTab.value === 'hot') {
    result.sort((a, b) => (b.likeCount + b.commentCount) - (a.likeCount + a.commentCount))
  } else if (activeTab.value === 'featured') {
    result = result.filter(article => article.likeCount > 200)
    result.sort((a, b) => b.likeCount - a.likeCount)
  }

  return result
})

// 监听搜索关键词变化，延迟搜索
let searchTimer = null
watch(searchKeyword, () => {
  if (searchTimer) {
    clearTimeout(searchTimer)
  }
  searchTimer = setTimeout(() => {
    hasMore.value = true
    void loadArticles()
  }, 500) // 500ms防抖
})

// 监听标签变化
watch(selectedTag, () => {
  hasMore.value = true
  void loadArticles()
})

// 监听tab变化
watch(activeTab, () => {
  hasMore.value = true
  void loadArticles()
})

// 方法
function handlePublish() {
  router.push('/community/publish')
}

function handleArticleClick(article) {
  router.push(`/community/articles/${article.id}`)
}

function handleSearch() {
  // 搜索逻辑通过watch处理
}

// 加载文章类型列表
async function loadTypes() {
  try {
    const response = await typeApi.listType()

    // 处理响应数据
    let typeList = []
    if (Array.isArray(response)) {
      typeList = response
    } else if (response && typeof response === 'object' && response.data && Array.isArray(response.data)) {
      typeList = response.data
    }

    // 提取类型名称列表
    popularTags.value = typeList.map(type => {
      return type.tName || type.tname || type.name || type
    })
  } catch (error) {
    void error
  }
}

onMounted(async () => {
  loadTypes() // 先加载类型列表
  hasMore.value = true
  await loadArticles() // 然后加载文章列表
  await setupIntersectionObserver()
})

onBeforeUnmount(() => {
  if (searchTimer) {
    clearTimeout(searchTimer)
  }
  if (intersectionObserver) {
    intersectionObserver.disconnect()
    intersectionObserver = null
  }
})
</script>

<style scoped>
.article-hall {
  min-height: calc(100vh - 64px);
  background: #f9fafb;
  padding-top: 0;
}

.hall-header {
  background: #ffffff;
  border-bottom: 1px solid #eef0f5;
  padding: 20px 0;
  position: sticky;
  top: 64px;
  z-index: 99;
  margin-top: 0;
}

.header-content {
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 24px;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.hall-title {
  font-size: 24px;
  font-weight: 700;
  color: #2b2f36;
  margin: 0;
}

.publish-btn {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 20px;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: #ffffff;
  border: none;
  border-radius: 8px;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.3s ease;
  box-shadow: 0 2px 8px rgba(102, 126, 234, 0.2);
}

.publish-btn:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
}

.publish-btn svg {
  width: 18px;
  height: 18px;
}

.filter-bar {
  background: #ffffff;
  border-bottom: 1px solid #eef0f5;
  padding: 16px 0;
}

.filter-content {
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 24px;
}

.filter-tabs {
  display: flex;
  gap: 8px;
  margin-bottom: 12px;
}

.tab-btn {
  padding: 8px 16px;
  background: #f9fafb;
  border: 1px solid #e5e7eb;
  border-radius: 8px;
  font-size: 14px;
  color: #6b7280;
  cursor: pointer;
  transition: all 0.2s ease;
}

.tab-btn:hover {
  background: #f3f4f6;
  color: #4b5563;
}

.tab-btn.active {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: #ffffff;
  border-color: #667eea;
}

.filter-tags {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

.tag-btn {
  padding: 6px 12px;
  background: #f9fafb;
  border: 1px solid #e5e7eb;
  border-radius: 20px;
  font-size: 13px;
  color: #6b7280;
  cursor: pointer;
  transition: all 0.2s ease;
}

.tag-btn:hover {
  background: #f3f4f6;
  border-color: #d1d5db;
}

.tag-btn.active {
  background: #667eea;
  color: #ffffff;
  border-color: #667eea;
}

.search-bar {
  background: #ffffff;
  padding: 16px 0;
  border-bottom: 1px solid #eef0f5;
}

.search-content {
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 24px;
}

.search-input-wrapper {
  position: relative;
  max-width: 600px;
}

.search-icon {
  position: absolute;
  left: 16px;
  top: 50%;
  transform: translateY(-50%);
  width: 20px;
  height: 20px;
  color: #9ca3af;
}

.search-input {
  width: 100%;
  padding: 12px 16px 12px 48px;
  border: 1px solid #e5e7eb;
  border-radius: 8px;
  font-size: 14px;
  background: #f9fafb;
  transition: all 0.2s ease;
}

.search-input:focus {
  outline: none;
  border-color: #667eea;
  background: #ffffff;
  box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
}

.article-list-container {
  max-width: 1200px;
  margin: 0 auto;
  padding: 24px;
}

.article-list-content {
  min-height: 400px;
}

.article-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: 24px;
}

.loading-state,
.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 80px 20px;
  color: #9ca3af;
}

.loading-state svg,
.empty-state svg {
  width: 64px;
  height: 64px;
  margin-bottom: 16px;
  color: #d1d5db;
}

.spinner {
  width: 48px;
  height: 48px;
  border: 4px solid #f3f4f6;
  border-top-color: #667eea;
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

.empty-state p {
  font-size: 16px;
  color: #6b7280;
}

.scroll-trigger {
  width: 100%;
  height: 1px;
}

.end-state {
  padding: 24px 0 40px;
  text-align: center;
  color: #9ca3af;
  font-size: 14px;
}
</style>

